/*
 * Copyright (c) 2024 endless-sky
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <string>
#include <functional>
#include "utils_noncopyable.h"

namespace El {
namespace Upgrade {

// 固件升级进度回调函数类型
// progress: 升级进度百分比(0-100)
// status: 当前升级状态描述(如: "Preparing", "Writing kernel", "Switching partition")
using UpgradeProgressCallback = std::function<void(int progress, const std::string& status)>;

/**
 * @brief 固件升级服务接口
 * 
 * 提供完整的A/B分区固件升级解决方案：
 * - 支持A/B双分区无缝升级，零停机时间
 * - 流式数据处理，边下载边写入，节省存储空间
 * - 支持CPIO归档封装镜像（kernel.img/rootfs.img/assets.img）
 * - 自动故障检测和回滚机制
 * - 原子性操作，确保升级过程安全可靠
 * 
 * 典型使用流程：
 * 1. 调用Prepare()初始化升级环境
 * 2. 调用SetProgressCallback()设置进度回调
 * 3. 循环调用StreamUpgradeData()传输升级包数据
 * 4. 调用CompleteUpgrade()完成升级并重启
 * 5. 系统重启后调用MarkBootSuccessful()确认升级成功
 */
class IUpgradeService {
public:
    virtual ~IUpgradeService() = default;

    /**
     * @brief 获取固件升级服务实例
     * @return 固件升级服务单例
     */
    static IUpgradeService &GetInstance();

    /**
     * @brief 启动升级服务
     *
     * 系统启动时调用此接口执行升级服务的初始化任务：
     * - 标记当前启动为成功状态，确认升级成功
     * - 检查版本变化并执行必要的迁移操作
     * - 初始化升级环境和服务状态
     * - 执行启动后的必要检查和维护任务
     *
     * @return true 启动成功, false 启动失败
     *
     * @note 通常在系统主进程启动完成后调用
     * @warning 必须在每次系统重启后调用，否则可能触发回滚
     */
    virtual bool Start() = 0;

    /**
     * @brief 初始化升级环境
     * 
     * 执行升级前的准备工作：
     * - 初始化MTD设备库
     * - 验证U-Boot环境配置
     * - 确定当前和目标分区
     * - 标记当前启动为成功状态
     * 
     * @return true 初始化成功, false 初始化失败
     */
    virtual bool InitializeUpgradeEnvironment() = 0;

    /**
     * @brief 中断升级进程
     * 
     * 立即停止当前的升级操作并清理资源：
     * - 取消正在进行的升级
     * - 清理MTD资源和缓冲区
     * - 重置升级状态
     * 
     * 注意：中断后的升级不可恢复，需要重新开始
     */
    virtual void AbortUpgrade() = 0;

    /**
     * @brief 设置升级进度回调函数
     * 
     * 设置用于接收升级进度通知的回调函数
     * 
     * @param callback 进度回调函数，接收两个参数：
     *                 - progress: 进度百分比(0-100)
     *                 - status: 当前状态描述
     */
    virtual void RegisterProgressCallback(UpgradeProgressCallback callback) = 0;

    /**
     * @brief 流式传输升级包数据
     * 
     * 接收升级包的数据流，支持边下载边升级。
     * 第一次调用时自动开始升级进程。
     * 
     * @param data 升级包数据指针，不能为nullptr
     * @param length 数据长度，必须大于0
     * @return true 数据处理成功, false 处理失败
     * 
     * @note 支持CPIO封装或直接流式传入镜像数据（kernel.img/rootfs.img/assets.img）
     * @warning 必须先调用InitializeUpgradeEnvironment()初始化
     */
    virtual bool StreamUpgradeData(const uint8_t *data, size_t length) = 0;

    /**
     * @brief 完成升级进程
     * 
     * 通知升级数据传输完成，执行最后的升级步骤：
     * - 切换U-Boot启动分区到新版本
     * - 清理临时数据和状态
     * - 自动重启系统以应用新固件
     * 
     * @return true 升级完成成功, false 升级完成失败
     * 
     * @warning 调用此函数后系统将自动重启
     * @note 重启后必须调用MarkBootSuccessful()确认升级成功
     */
    virtual bool CompleteUpgrade() = 0;

    /**
     * @brief 获取当前启动分区信息
     * 
     * 返回A/B分区的详细信息，包括当前活跃分区、
     * 各分区的版本号、启动状态等。
     * 
     * @return JSON格式的分区信息字符串
     * 
     * 返回示例：
     * {
     *   "current_slot": "A",
     *   "slot_a": { "bootable": true, "successful": true },
     *   "slot_b": { "bootable": false, "successful": false }
     * }
     */
    virtual std::string GetBootPartitionInfo() = 0;


    /**
     * @brief 强制切换到指定分区
     * 
     * 紧急情况下强制切换启动分区，用于系统恢复。
     * 此操作会立即生效，下次重启时使用指定分区。
     * 
     * @param slot 目标分区标识 ("A" 或 "B", 大小写不敏感)
     * @return true 切换成功, false 切换失败
     * 
     * @warning 仅在紧急恢复情况下使用，正常升级请使用CompleteUpgrade()
     * @note 切换后需要重启系统才能生效
     */
    virtual bool SwitchToBootPartition(const std::string& slot) = 0;

    /**
     * @brief 获取当前升级状态
     * 
     * 返回升级进程的当前状态。
     * 
     * @return 升级状态字符串
     * 
     * 可能的状态值：
     * - "IDLE": 未开始升级
     * - "READY": 已初始化，等待数据
     * - "UPGRADING": 正在升级
     * - "COMPLETED": 升级完成
     * - "FAILED": 升级失败
     * - "INTERRUPTED": 升级被中断
     */
    virtual std::string GetCurrentUpgradeStatus() = 0;

    /**
     * @brief 获取最后的错误信息
     * 
     * 返回最近一次升级操作失败的详细错误信息。
     * 如果没有错误，返回空字符串。
     * 
     * @return 错误信息字符串，无错误时为空
     * 
     * @note 错误信息会在下次成功操作后被清空
     */
    virtual std::string GetLastErrorMessage() = 0;
};

} // namespace Upgrade
} // namespace El
